home *** CD-ROM | disk | FTP | other *** search
/ HTBasic 9.3 / HTBasic 9.3.iso / 83win / data1.cab / DLL_Toolkit / Source / HTBLink / BLink.cpp next >
Encoding:
C/C++ Source or Header  |  2001-03-02  |  10.8 KB  |  411 lines

  1. // BLink.cpp : Defines the initialization routines for the DLL.
  2. //
  3.  
  4. #include "stdafx.h"
  5. #include "BLink.h"
  6. #include "Link.h"
  7. #include "assert.h"
  8. #include "dialogthread.h"
  9. #include "export.h"
  10.  
  11. #ifdef _DEBUG
  12. #define new DEBUG_NEW
  13. #undef THIS_FILE
  14. static char THIS_FILE[] = __FILE__;
  15. #endif
  16.  
  17. #define LINKDATASIZE 256
  18. #define MAXINSTANCES 4
  19. #define MAXLINKS 20
  20. #define EVENTTIMEOUT 5000L            // 5 seconds
  21. #define MUTEXTIMEOUT 10000L            // 10 seconds
  22. #define SIZEOFBASICINTEGER 2
  23. #define SIZEOFBASICLONG 4
  24. #define SIZEOFBASICREAL 8
  25. #define SIZEOFBASICSTRING 0
  26. #define SUCCESS 0
  27. #define LINKLIMIT 1
  28. #define INVALIDTYPE 2
  29. #define INVALIDDIRECTION 3
  30. #define INVALIDLINKID 4
  31. #define LINKIDEXISTS 5
  32. #define SERVEREXISTS 6
  33. #define NOTSECURE 7
  34. #define NOCREATELINK 8
  35. #define WHOLELIST 0
  36. #define GETID 1
  37. #define INVALIDOPTION -1
  38. #define DATAMISMATCH 1
  39.  
  40. //
  41. //    Note!
  42. //
  43. //        If this DLL is dynamically linked against the MFC
  44. //        DLLs, any functions exported from this DLL which
  45. //        call into MFC must have the AFX_MANAGE_STATE macro
  46. //        added at the very beginning of the function.
  47. //
  48. //        For example:
  49. //
  50. //        extern "C" BOOL PASCAL EXPORT ExportedFunction()
  51. //        {
  52. //            AFX_MANAGE_STATE(AfxGetStaticModuleState());
  53. //            // normal function body here
  54. //        }
  55. //
  56. //        It is very important that this macro appear in each
  57. //        function, prior to any calls into MFC.  This means that
  58. //        it must appear as the first statement within the 
  59. //        function, even before any object variable declarations
  60. //        as their constructors may generate calls into the MFC
  61. //        DLL.
  62. //
  63. //        Please see MFC Technical Notes 33 and 58 for additional
  64. //        details.
  65. //
  66.  
  67. /////////////////////////////////////////////////////////////////////////////
  68. // CBLinkApp
  69.  
  70. BEGIN_MESSAGE_MAP(CBLinkApp, CWinApp)
  71.     //{{AFX_MSG_MAP(CBLinkApp)
  72.         // NOTE - the ClassWizard will add and remove mapping macros here.
  73.         //    DO NOT EDIT what you see in these blocks of generated code!
  74.     //}}AFX_MSG_MAP
  75. END_MESSAGE_MAP()
  76.  
  77. /////////////////////////////////////////////////////////////////////////////
  78. // CBLinkApp construction
  79.  
  80. CBLinkApp::CBLinkApp()
  81. {
  82.     // TODO: add construction code here,
  83.     // Place all significant initialization in InitInstance
  84. }
  85.  
  86. /////////////////////////////////////////////////////////////////////////////
  87. // The one and only CBLinkApp object
  88.  
  89. CBLinkApp theApp;
  90.  
  91.  
  92. #pragma data_seg("LinkData")
  93.  
  94. char g_DataBlock[LINKDATASIZE] = {NULL};
  95. short g_RequestID = 0;
  96. short g_RequestInstance = 0;
  97. short g_StringSize = 0;
  98. short g_NextInstanceID = 0;
  99. short g_ServerList[MAXLINKS][2] = {0,0};
  100. short g_ServerCount = 0;
  101.  
  102. #pragma data_seg()
  103.  
  104.  
  105. short g_InstanceID;
  106. Link* g_pLinks[MAXLINKS] = {NULL};
  107. short g_LinkCount = 0;
  108. HANDLE g_hSetupMutex;
  109. HANDLE g_hMutex;
  110. HANDLE g_hRequestEvents[MAXINSTANCES];
  111. HANDLE g_hAnswerEvents[MAXINSTANCES];
  112. HANDLE g_hShutDown[MAXINSTANCES];
  113. BOOL g_ListenThread = FALSE;
  114. BOOL g_StopLinkRequest = FALSE;
  115. CWinThread * g_pThread;
  116.  
  117.  
  118. int GetMutex(HANDLE hMutex)
  119. {    DWORD result;
  120.     
  121.     result = WaitForSingleObject(hMutex,MUTEXTIMEOUT);    // get mutex for control of data
  122.  
  123.     if (result == WAIT_OBJECT_0)
  124.     {    return(1);
  125.     }
  126.     else
  127.     {    return(0);
  128.     }
  129. }
  130.  
  131. int WaitEvent(HANDLE hEvent)
  132. {    DWORD result;
  133.  
  134.     result = WaitForSingleObject(hEvent,EVENTTIMEOUT);    // wait for return signal
  135.  
  136.     if (result == WAIT_OBJECT_0)
  137.     {    return(1);
  138.     }
  139.     else
  140.     {    return(0);
  141.     }
  142. }
  143.  
  144.  
  145. short UpdateID(short index)
  146. {    short result = 0;
  147.     
  148.     if (GetMutex(g_hMutex))                // grab the mutex for shared data access
  149.     {    int ServerCheck = 0;            
  150.                     
  151.         // cycle ServerList to get which instance of basic to request from
  152.         while (ServerCheck < g_ServerCount && g_pLinks[index]->m_LinkID != g_ServerList[ServerCheck][0])
  153.         {    ServerCheck++;
  154.         }
  155.         if (ServerCheck == g_ServerCount)    // there is no server for this ID
  156.         {    ReleaseMutex(g_hMutex);
  157.             return(0);
  158.         }
  159.                         
  160.         g_RequestID = g_pLinks[index]->m_LinkID;            // place requested ID into shared data for server to see
  161.         g_RequestInstance = g_InstanceID;    // send our instance so the server knows who to send back to
  162.             
  163.         SetEvent(g_hRequestEvents[g_ServerList[ServerCheck][1]]);    // signal event so request will be processed
  164.                         
  165.         if (WaitEvent(g_hAnswerEvents[g_InstanceID]))                // wait for answer
  166.         {    // get data sent and place in basic variable
  167.             if (g_pLinks[index]->m_DataSize)
  168.             {    memcpy(g_pLinks[index]->m_pData,&g_DataBlock,g_pLinks[index]->m_DataSize);
  169.             }
  170.             else
  171.             {    strncpy((char *)g_pLinks[index]->m_pData,(char *)&g_DataBlock,g_StringSize);
  172.                 short* pStringSize = (short*)((char *)g_pLinks[index]->m_pData - 2);
  173.                 *pStringSize = g_StringSize;            // update Basic string size
  174.             }
  175.             result = 1;
  176.         }
  177.         else
  178.         {    result = 0;                        // no answer
  179.         }
  180.  
  181.         ReleaseMutex(g_hMutex);
  182.     }        
  183.  
  184.     return(result);
  185. }
  186.  
  187. short Setlink(short LinkID,void* pData,char* type,char* direction)
  188. {    short size;
  189.     int CheckForID;
  190.     BOOL InFlag = FALSE;
  191.  
  192.     if (g_LinkCount == MAXLINKS)                    // check to see if at link limit
  193.     {    return(LINKLIMIT);
  194.     }
  195.  
  196.     // get size from type param
  197.     if (!stricmp("INTEGER",type))
  198.     {    size = SIZEOFBASICINTEGER;
  199.     }
  200.  
  201.     else if (!stricmp("LONG",type))
  202.     {    size = SIZEOFBASICLONG;
  203.     }
  204.  
  205.     else if (!stricmp("REAL",type))
  206.     {    size = SIZEOFBASICREAL;
  207.     }
  208.  
  209.     else if (!stricmp("STRING",type))
  210.     {    size = SIZEOFBASICSTRING;
  211.     }
  212.     else    // bad type
  213.     {    return(INVALIDTYPE);
  214.     }
  215.  
  216.     if (stricmp("IN",direction) && stricmp("OUT",direction))        // check for valid direction
  217.     {    return(INVALIDDIRECTION);
  218.     }
  219.  
  220.     if (LinkID == 0)                                                // do not allow LinkID of 0
  221.     {    return(INVALIDLINKID);
  222.     }
  223.  
  224.     for (CheckForID = 0;CheckForID < g_LinkCount;CheckForID++)
  225.     {    if (LinkID == g_pLinks[CheckForID]->m_LinkID)
  226.         {    return(LINKIDEXISTS);
  227.         }
  228.     }
  229.  
  230.     if (!stricmp("IN",direction))
  231.     {    InFlag = TRUE;
  232.     }
  233.  
  234.     g_pLinks[g_LinkCount] = new Link(LinkID,pData,size,InFlag);            // create new link object and hold ptr in array
  235.  
  236.     if (g_pLinks != NULL)
  237.     {    g_LinkCount++;
  238.         
  239.         if (!stricmp("OUT",direction))                                // if OUT direction we need to setup
  240.         {    if (GetMutex(g_hMutex))                                    // secure data
  241.             {    int loop;
  242.                 
  243.                 for (loop = 0;loop < g_ServerCount;loop++)            // check to see if link ID already has server
  244.                 {    if (g_ServerList[loop][0] == LinkID)
  245.                     {    ReleaseMutex(g_hMutex);                        // let go of data
  246.                         return(SERVEREXISTS);
  247.                     }
  248.                 }
  249.  
  250.                 g_ServerList[g_ServerCount][0] = LinkID;            // save data into shared area
  251.                 g_ServerList[g_ServerCount][1] = g_InstanceID;        
  252.                 g_ServerCount++;
  253.  
  254.                 ReleaseMutex(g_hMutex);                                // let go of data
  255.             }
  256.             else                                                    // unable to get mutex
  257.             {    return(NOTSECURE);
  258.             }
  259.         }
  260.  
  261.         return(SUCCESS);                                                    // success
  262.     }
  263.     else                                                            // new failed
  264.     {    return(NOCREATELINK);
  265.     }
  266. }
  267.  
  268.  
  269. short Getlink(short LinkID,short option)
  270. {    // option WHOLELIST = the whole list once
  271.     // option GETID = get ID
  272.     short result = 0;
  273.  
  274.     switch (option)
  275.     {    case WHOLELIST:
  276.         {    int loop;
  277.             int check = 0;
  278.  
  279.             // cycle list of links and update each
  280.             for (loop = 0;loop < g_LinkCount;loop++)
  281.             {    if (g_pLinks[loop]->m_InFlag)
  282.                 {    check = UpdateID(loop);
  283.                     if (check)
  284.                     {    result++;
  285.                     }
  286.                 }
  287.             }
  288.             break;
  289.         }
  290.  
  291.         case GETID:
  292.         {    int loop;
  293.  
  294.             // cycle list of links to find the one specified
  295.             for (loop = 0;loop < g_LinkCount;loop++)
  296.             {    if (LinkID == g_pLinks[loop]->m_LinkID && g_pLinks[loop]->m_InFlag)    // if this is the link were looking for
  297.                 {    result = UpdateID(loop);    
  298.                 }
  299.             }
  300.             break;
  301.         }
  302.  
  303.         default:
  304.             return(INVALIDOPTION);
  305.             break;
  306.  
  307.     }
  308.     return(result);
  309. }
  310.  
  311. void StartServer()
  312. {    while (!g_StopLinkRequest)
  313.     {    if (WaitEvent(g_hRequestEvents[g_InstanceID]))                // wait for requests directed at this instance
  314.         {    int loop = 0;
  315.  
  316.             while (loop < g_LinkCount && g_RequestID != g_pLinks[loop]->m_LinkID)    // find this ID
  317.             {    loop++;
  318.             }
  319.  
  320.             if (loop == g_LinkCount)
  321.             {    MessageBox(NULL,"Server data mismatch","Blink Error",MB_OK);
  322.             }
  323.             else
  324.             {    if (g_pLinks[loop]->m_DataSize)                            // if not a string
  325.                 {    memcpy(&g_DataBlock,g_pLinks[loop]->m_pData,g_pLinks[loop]->m_DataSize);    // place data in shared area
  326.                 }
  327.                 else                                                    // is a string
  328.                 {    g_StringSize = *((short*)((char *)g_pLinks[loop]->m_pData - 2));            // place string size in shared area
  329.                     strncpy((char *)&g_DataBlock,(char *)g_pLinks[loop]->m_pData,g_StringSize); // place data in shared area
  330.                 }                                            
  331.         
  332.                 SetEvent(g_hAnswerEvents[g_RequestInstance]);            // reset event to say we answered it
  333.             }
  334.         }    
  335.     } // while (!g_StopLinkRequest)
  336.                                             // thread is shutting down
  337.     SetEvent(g_hShutDown[g_InstanceID]);
  338. }
  339.  
  340. void Startlink()
  341. {    if (!g_ListenThread)
  342.     {    g_StopLinkRequest = FALSE;
  343.         g_ListenThread = TRUE;
  344.         g_pThread = AfxBeginThread(RUNTIME_CLASS (DialogThread));    // create thread to execute dialog
  345.     }
  346. }
  347.  
  348. void Stoplink()
  349. {    if (g_ListenThread)
  350.     {    g_StopLinkRequest = TRUE;                                        // set flag to request thread exit
  351.         WaitForSingleObject(g_hShutDown[g_InstanceID],INFINITE);    // wait for return signal
  352.         g_ListenThread = FALSE;    
  353.     }
  354. }
  355.  
  356.  
  357.  
  358. BOOL CBLinkApp::InitInstance() 
  359. {    g_hSetupMutex = CreateMutex(NULL,FALSE,"StartupMutex");
  360.     g_hMutex = CreateMutex(NULL,FALSE,"LinkMutex");
  361.     g_hRequestEvents[0] = CreateEvent(NULL,FALSE,FALSE,"RequestEventzero");
  362.     g_hRequestEvents[1] = CreateEvent(NULL,FALSE,FALSE,"RequestEventone");
  363.     g_hRequestEvents[2] = CreateEvent(NULL,FALSE,FALSE,"RequestEventtwo");
  364.     g_hRequestEvents[3] = CreateEvent(NULL,FALSE,FALSE,"RequestEventthree");
  365.     g_hAnswerEvents[0] = CreateEvent(NULL,FALSE,FALSE,"AnswerEventzero");
  366.     g_hAnswerEvents[1] = CreateEvent(NULL,FALSE,FALSE,"AnswerEventone");
  367.     g_hAnswerEvents[2] = CreateEvent(NULL,FALSE,FALSE,"AnswerEventtwo");
  368.     g_hAnswerEvents[3] = CreateEvent(NULL,FALSE,FALSE,"AnswerEventthree");
  369.     g_hShutDown[0] = CreateEvent(NULL,FALSE,FALSE,"ShutDownone");
  370.     g_hShutDown[1] = CreateEvent(NULL,FALSE,FALSE,"ShutDowntwo");
  371.     g_hShutDown[2] = CreateEvent(NULL,FALSE,FALSE,"ShutDownthree");
  372.     g_hShutDown[3] = CreateEvent(NULL,FALSE,FALSE,"ShutDownfour");
  373.     
  374.     if (GetMutex(g_hSetupMutex) && g_NextInstanceID < MAXINSTANCES)            // grab setup mutex
  375.     {    g_InstanceID = g_NextInstanceID;                            // get our instance ID
  376.         g_NextInstanceID++;                                            // Update for the next Instance
  377.         
  378.         ReleaseMutex(g_hSetupMutex);                                // let go of data
  379.     }
  380.     else
  381.     {    return(FALSE);                                                // fail to load DLL if fail to get instance ID
  382.     }
  383.  
  384.     return CWinApp::InitInstance();
  385. }
  386.  
  387.  
  388.  
  389. int CBLinkApp::ExitInstance() 
  390. {    int ServerCheck = 0;
  391.     
  392.     Stoplink();
  393.  
  394.     WaitForSingleObject(g_hMutex,INFINITE);
  395.     
  396.     // cycle ServerList to clean out this instance
  397.     while (ServerCheck < g_ServerCount)
  398.     {    if (g_InstanceID == g_ServerList[ServerCheck][1])
  399.         {    g_ServerList[ServerCheck][0] = g_ServerList[g_ServerCount - 1][0];
  400.             g_ServerList[ServerCheck][1] = g_ServerList[g_ServerCount - 1][1];
  401.             g_ServerCount--;
  402.         }
  403.         else
  404.         {    ServerCheck++;
  405.         }
  406.     }
  407.  
  408.     ReleaseMutex(g_hMutex);
  409.     return CWinApp::ExitInstance();
  410. }
  411.